package com.bestv.servlet;

import com.bestv.database.dao.DaoFactory;
import com.bestv.database.data.BestvDataManager;
import com.bestv.database.vo.*;
import com.bestv.engine.filter.Filter;
import com.bestv.engine.filter.Filters;
import com.bestv.engine.filter.MediaCodeFilter;
import com.bestv.engine.filter.MovieFilter;
import com.bestv.engine.model.RecommendationRule;
import com.bestv.engine.recommender.Recommender;
import com.bestv.engine.recommender.RecommenderManager;
import com.bestv.utils.common.Constants;
import com.bestv.utils.common.GenerateId;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 推荐引擎外部调用接口
 * User: Henry
 * Date: 14-4-29
 */
public class RecommendServlet extends HttpServlet {
    private Logger accessLogger = LoggerFactory.getLogger("accessLogger");

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=UTF-8");
        String strXML = generateRecommendation(request);
        PrintWriter writer = response.getWriter();
        writer.append(strXML);
    }

    private String generateRecommendation(HttpServletRequest request) throws UnsupportedEncodingException {
        String method = request.getParameter("method");
        if (StringUtils.isBlank(method)) method = this.getInitParameter("method");
        if (StringUtils.isBlank(method)) return "";
        String methodDup = method;
        Filters filters = new Filters();

        String charset = request.getParameter("charset");
        if (StringUtils.isBlank(charset)) charset = "UTF-8";

        Series series = null;
        String programIdRawDup = null;
        String programIdRaw = request.getParameter("pid");
        if (StringUtils.isNotBlank(programIdRaw)) {
            programIdRawDup = programIdRaw;
            Program program = DaoFactory.getProgramDao().findByMediaCode(programIdRaw);
            if (program != null) programIdRaw = program.getSeriesCode();
            series = DaoFactory.getSeriesDao().findByMediaCode(programIdRaw);
        }

        String seriesIdRaw = request.getParameter("sid");
        if (series == null && StringUtils.isNotBlank(seriesIdRaw)) {
            series = DaoFactory.getSeriesDao().findByMediaCode(seriesIdRaw);
        }

        String seriesName = request.getParameter("name");
        if (StringUtils.isBlank(seriesName)) seriesName = "";
        seriesName = new String(seriesName.getBytes(Constants.CHARSET_NAME), charset);

        if (series == null && StringUtils.isNotBlank(seriesName)) {
            series = DaoFactory.getSeriesDao().findByName(seriesName);
            if (series != null) seriesIdRaw = series.getMediaCode();
        }

        String typeName = request.getParameter("type");
        if (StringUtils.isBlank(typeName)) typeName = "";
        typeName = new String(typeName.getBytes(Constants.CHARSET_NAME), charset);
        ProgramType type = BestvDataManager.getInstance().getTypeFromAlias(typeName);

        String tagName = request.getParameter("tag");
        if (StringUtils.isBlank(tagName)) tagName = "";
        tagName = new String(tagName.getBytes(Constants.CHARSET_NAME), charset);

        if (series == null && type != null) {
            series = new Series();
            series.setId(-1L * type.getTypeId());
            series.setMediaCode(StringUtils.isNotBlank(seriesIdRaw) ? seriesIdRaw : programIdRaw);
            series.setName(seriesName);
            series.setTypeId(type.getTypeId());
            series.setTags(tagName);
        }

        String userIdRaw = request.getParameter("uid");
        User user = null;
        if (StringUtils.isNotBlank(userIdRaw)) {
            user = DaoFactory.getUserDao().findByMediaCode(userIdRaw);
        }
        if (user == null) {
            user = new User();
            user.setId(0L);
            user.setMediaCode(userIdRaw);
        }

        String page = request.getParameter("page");
        if (StringUtils.isBlank(page)) page = "";

        String categoryName = request.getParameter("category");
        if (StringUtils.isBlank(categoryName)) categoryName = "";
        categoryName = new String(categoryName.getBytes(Constants.CHARSET_NAME), charset);

        String countRaw = request.getParameter("rcount");
        if (StringUtils.isBlank(countRaw)) countRaw = "10";
        int maxCount = 2 * Integer.parseInt(countRaw);

        String ruleFormat = request.getParameter("format");
        if (StringUtils.isBlank(ruleFormat)) ruleFormat = getInitParameter("format");
        if (StringUtils.isBlank(ruleFormat)) ruleFormat = "xml";

        String isByGenreRaw = request.getParameter("bygenre");
        if (StringUtils.isBlank(isByGenreRaw)) isByGenreRaw = "";
        boolean isByGenre = "true".equalsIgnoreCase(isByGenreRaw);

        String biz = request.getParameter("biz");
        if (StringUtils.isBlank(biz)) biz = "";

        String isByBizRaw = request.getParameter("bybiz");
        if (StringUtils.isBlank(isByBizRaw)) isByBizRaw = "";
        boolean isByBiz= "true".equalsIgnoreCase(isByBizRaw);

        String pviewHistory = request.getParameter("pviewhistory");
        String sviewHistory = request.getParameter("sviewhistory");
        String[] viewHistory = String.format("%s|%s|%s|%s", pviewHistory, sviewHistory, programIdRaw, seriesIdRaw).split("\\|");
        Filter mediaCodeFilter = new MediaCodeFilter(viewHistory);
        filters.add(mediaCodeFilter);

        Filter programFilter = new MovieFilter(programIdRawDup, isByBiz ? biz : null, ruleFormat);
        filters.add(programFilter);

        Item item = series;
        Recommender recommender;
        RecommendationRule rule = new RecommendationRule();
        RecommenderManager recommenderManager = RecommenderManager.getInstance();
        String baseInfo = null;

        if (Constants.RECOMMEND_METHOD_PROGRAM.equals(method) || Constants.RECOMMEND_METHOD_SERIES.equals(method)) {
            if (item != null) {
                method = item.isSeries() ? Constants.RECOMMEND_METHOD_SERIES : Constants.RECOMMEND_METHOD_PROGRAM;
                recommender = recommenderManager.getRecommender(method, item.getTypeId(), user.getAbGroup());
                rule = recommender.recommend(item, maxCount, filters, isByGenre);
                rule.setTag(item.getTypeId());
                baseInfo = String.format("%s|%s|%s|%s|%s|%s|%s|%s", recommender.getName(), method, user.getId(), user.getMediaCode(), item.getId(), item.getMediaCode(), item.getName(), item.getTypeId());
            } else {
                method = Constants.RECOMMEND_METHOD_PERSONALIZED;
            }
        }

        if (Constants.RECOMMEND_METHOD_SCHEDULE.equals(method)){
            if(item!=null) {
                method = item.isSeries() ? Constants.RECOMMEND_METHOD_SERIES : Constants.RECOMMEND_METHOD_SCHEDULE;
                recommender = recommenderManager.getRecommender(method, item.getTypeId(), null);
                rule = recommender.recommend(item, maxCount, filters, isByGenre);
                baseInfo = String.format("%s|%s|%s|%s|%s|%s|%s|%s", recommender.getName(), method, user.getId(), user.getMediaCode(), item.getId(), item.getMediaCode(), item.getName(), item.getTypeId());
            }else{
                method = Constants.RECOMMEND_METHOD_PERSONALIZED;
            }
        }

        if (Constants.RECOMMEND_METHOD_PERSONALIZED.equals(method)) {
            if (user != null) {
                recommender = recommenderManager.getRecommender(method, null, user.getAbGroup());
                rule = recommender.recommend(user, maxCount, filters, isByGenre);
                rule.setPreference("言情剧|传记剧|偶像剧|动作|喜剧");
                baseInfo = String.format("%s|%s|%s|%s|%s|%s|%s|%s", recommender.getName(), method, user.getId(), user.getMediaCode(), null, null, null, null);
            }
        }

        if (Constants.RECOMMEND_METHOD_PREFERENCE.equals(method)) {
            String strMovieGenres = request.getParameter("moviegenres");
            if (strMovieGenres == null) strMovieGenres = "";
            strMovieGenres = new String(strMovieGenres.getBytes(Constants.CHARSET_NAME), charset);
            String[] movieGenres = strMovieGenres.replace(',','|').split("\\|");
            for (String tag : movieGenres) {

            }

            String strSeriesGenres = request.getParameter("seriesgenres");
            if (strSeriesGenres == null) strSeriesGenres = "";
            strSeriesGenres = new String(strSeriesGenres.getBytes(Constants.CHARSET_NAME), charset);
            String[] seriesGenres = strSeriesGenres.replace(',','|').split("\\|");
        }

        if (Constants.RECOMMEND_METHOD_HOTTEST.equals(method) || Constants.RECOMMEND_METHOD_LATEST.equals(method)) {
            if (item != null) {
                item.setId(100 * item.getId());
                recommender = recommenderManager.getRecommender(method, null, null);
                rule = recommender.recommend(item, maxCount, filters, isByGenre);
                baseInfo = String.format("%s|%s|%s|%s|%s|%s|%s|%s", recommender.getName(), method, user.getId(), user.getMediaCode(), item.getId(), item.getMediaCode(), item.getName(), item.getTypeId());
            }
        }

        long requestId = GenerateId.getInstance().getLongRandomId();
        rule.setRequestId(requestId);
        rule.setMethod(methodDup);
        if (baseInfo != null) {
            DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            accessLogger.info("{}|{}|{}|{}|{}|{}", fmt.format(new Date()), requestId, baseInfo, categoryName, isByGenre, page);
        }
        return rule.format(ruleFormat);
    }
}
